home *** CD-ROM | disk | FTP | other *** search
- /*
- * File: SoupDrink.c
- *
- * Contains: Demonstration application for the CDIL and FDIL
- * This is the Macintosh version of SoupDrink - see SOUPDRNK.C for Windows.
- *
- * Written by: Rob Langhorne, J. Christopher Bell and David Fedor
- *
- * Copyright: © 1995-1996 by Apple Computer, Inc. All rights reserved.
- *
- * Notes:
- * This is nearly all of the Macintosh-specific code. It is not intended to be
- * good Mac sample code :-) but it works to demonstrate & test how the DILs work.
- *
- * Nearly all of the DIL code can be found in engine.c. The only interesting
- * DIL code in here can be found near the top - in SetupPortMenu and InitializePipe.
- *
- * You may incorporate this sample code into your applications without
- * restriction. This sample code has been provided "AS IS" and the
- * responsibility for its operation is 100% yours. You are not
- * permitted to modify and redistribute the source as "DTS Sample Code."
- * If you are going to re-distribute the source, we require that you
- * make it clear in the source that the code was descended from
- * Apple-provided sample code, but that you've made changes.
- */
-
- #include <Types.h>
- #include <memory.h>
- #include <Packages.h>
- #include <Errors.h>
- #include <quickdraw.h>
- #include <fonts.h>
- #include <dialogs.h>
- #include <windows.h>
- #include <menus.h>
- #include <events.h>
- #include <OSEvents.h>
- #include <Desk.h>
- #include <diskinit.h>
- #include <OSUtils.h>
- #include <resources.h>
- #include <toolutils.h>
- #include <AppleEvents.h>
- #include <string.h>
- #include <Strings.h>
- #include <stdio.h>
-
- #define forMac // this is a Macintosh-only source file...
- #include "DILCPipe.h"
- #include "HLFDIL.h"
- #include "AppDialogs.h"
- #include "SoupDrink.h"
- #include "Engine.h"
-
-
-
- /****** Function prototypes *******/
- void EventLoop(void) ;
- Boolean DoMenuItem(long val) ;
- void DoDiskEvents(long dinfo) ;
- void DoDeskAccCall(MenuHandle themenu, long theit) ;
- void DisableExpertFuncs(void);
- void EnableExpertFuncs(void);
-
-
- /******** Global variables **********/
-
- // UI stuff
- MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gTestHandle, gPortHandle, gFuncMenuHandle;
- Boolean gQuit; // Flags for application state
- int gNumPorts; // how many ports are in our port menu
-
- // Configuration options set through menus
- long gWhichPort, // the number in the menu of which port to use
- gWhichTool; // Selector for which communications tool to use
- Boolean gEncrypt = false, // Toggles for advanced reading and writing
- gByteSwap = false,
- gUseUnicode = false,
- gExpertMode = false;
-
- // the following are globals set in here, used in Engine.c
- void *ourPipe;
- void *gThisObject; /* This is the only DIL frame active at one time in this app */
- int gInputMode; /* drink mode (receive frames) or spit mode (receive strings) */
- char gReceivedString[kMAXSTR]; /* received string; used in 'spit mode' */
- long gReceivedStringLen; /* received string length (see above) */
- char gTempBuffer [256]; /* a global string buffer for input dialogs, etc */
-
-
- // SetupPortMenu() demonstrates finding the available ports available on your machine.
- // Different model MacOS computers have different ports, and the port names can be
- // localized into other languages.
- //
- // The port names are gotten from the Communications Toolbox and placed directly into
- // menu items. Note that InitCRM() is not called - that is called by the DILs as part
- // of CDInitCDIL(). (Future versions of the DILs might not call it, though - watch
- // for more information on this.)
- //
- // SoupDrink has a "config" menu to which this function adds port names. When it comes
- // time to call CDPipeInit, the port name is taken directly out of the menu.
- //
- // The basis for this routine was stolen from:
- // http://dev.info.apple.com/source/code/Snippets/Communications_Toolbox/FindSerialPorts/ReadMe.html
-
- #include <CommResources.h>
- #include <CRMSerialDevices.h>
-
- void SetupPortMenu()
- {
- CRMRec c;
- CRMRecPtr cPtr = &c;
- CRMSerialPtr serialPtr;
-
- gNumPorts = 0;
- c.crmDeviceType = crmSerialDevice;
- c.crmDeviceID = 0;
- while (cPtr != nil) {
- cPtr = (CRMRecPtr)CRMSearch(&c);
- if (cPtr) {
- serialPtr = (CRMSerialPtr)cPtr->crmAttributes;
- AppendMenu(gPortHandle, *(serialPtr->name)); // this is a Pascal-style string, which is what AppendMenu wants.
- gNumPorts++;
- c.crmDeviceID = cPtr->crmDeviceID;
- }
- }
- gWhichPort = kFirstPortItem; // default to the first port in the list
- if (gNumPorts)
- CheckItem(gPortHandle, gWhichPort, true); // put a checkmark next to it.
- }
-
-
- /*
- * InitializePipe
- *
- * Purpose: This function sets up port options for the CDIL function called CDPipeInit.
- *
- * Note that if you do not "dispose" of the connection, the port can be locked and you will
- * get the "port busy" error which will make life difficult for both you and users. It would
- * be best if the function which Initializes the pipe takes responsibility for disposing of
- * of the pipe.
- */
- OSErr InitializePipe ()
- {
- OSErr fErr;
- char Port[100];
-
- // Copy the text for the port right out of the menu item.
- // It'll look like "Modem Port" but could be localized into another language!
- getitem(gPortHandle, gWhichPort, Port);
-
- switch (gWhichTool) {
- case kSerialTool:
- fErr = CDPipeInit(ourPipe, "Serial","","Baud 38400 dataBits 8 Parity None Port ", Port, kDefaultBufferSize, kDefaultBufferSize);
- break;
- case kModemTool:
- fErr = CDPipeInit(ourPipe, "Modem","","ModemType \"Newton Serial Connection\" dataBits 8 Parity None Baud 38400 Port ", Port, kDefaultBufferSize, kDefaultBufferSize);
- break;
- case kADSPTool:
- fErr = CDPipeInit(ourPipe, "ADSP","My Desktop Mac","LocalADSPType \"SoupDrink\" RegisterName 1 LocalADSPName ", Port, kDefaultBufferSize, kDefaultBufferSize);
- break;
- case kIRTool:
- fErr = CDPipeInit(ourPipe, "IR","","", Port, kDefaultBufferSize, kDefaultBufferSize);
- break;
- }
-
- return fErr;
- }
-
- void ListenCallback( CommErr errorValue, long refCon )
- // This is only used by the "expert" mode, to test asynchronous listening...
- {
- long length=5;
-
- if (errorValue)
- PostAlertMessage("CDPipeAccept asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
- else {
- errorValue = CDPipeAccept(ourPipe) ;
- if (errorValue)
- PostAlertMessage("CDPipeAccept asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
- else {
- errorValue = CDPipeWrite(ourPipe, (void *)"asdf\4", &length, true,0,0,600,0,0); // will generate an error on the Newton side
- if (errorValue)
- PostAlertMessage("CDPipeWrite asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
- }
- }
- }
-
-
- /*
- * encryptProc
- *
- * encryptProc is the encryption callback function
- */
- static void encryptProc ( void *pData, Size Count, long refCon )
- {
- Str255 refConStr;
- char * localStr;
-
-
- localStr = (char *) NewPtrClear(Count + 1);
- if (!localStr)
- return;
-
- strcpy(localStr, (char *)pData);
- sprintf((char*) refConStr, "%d", refCon);
- PostAlertMessage("We have encrypted:", (char*) localStr, " Reference constant: ", (char*) refConStr);
- }
-
-
- /*
- * decryptProc
- *
- * decryptProc is the decryption callback function
- */
- static void decryptProc ( void *pData, Size Count, long refCon )
- {
- Str255 refConStr;
- char * localStr;
-
- localStr = (char *)NewPtrClear(Count + 1);
- if (!localStr)
- return;
-
- strcpy(localStr,(char *) pData);
- NumToString(Count, (unsigned char*) gTempBuffer);
- sprintf((char*) refConStr, "%d", refCon);
- PostAlertMessage("We have encrypted:", localStr, "Reference constant: ",(char*) refConStr);
- }
-
-
- /* StateStrings
- *
- * Purpose: return state string based on state number from the CDILs
- * (as a pascal string)
- * note, if theErr is greater than 50, it is a user CDIL error
- */
- char* StateStrings(int theState, Str255 theString)
- {
- char* s;
- char theNum[128];
-
- switch (theState) {
- case kCDIL_Uninitialized: s = "CDIL is uninitialized."; break;
- case kCDIL_InvalidConnection: s = "CDIL tried to bring up connection, but it failed."; break;
- case kCDIL_Disconnected: s = "CDIL is disconnected."; break;
- case kCDIL_Listening: s = "CDIL is listening for a connection."; break;
- case kCDIL_ConnectPending: s = "A CDIL connection is pending."; break;
- case kCDIL_Connected: s = "CDIL is connected."; break;
- case kCDIL_Busy: s = "CDIL is busy (either reading or writing)."; break;
- case kCDIL_Aborting: s = "CDIL is aborting."; break;
- case kCDIL_Startup: s = "CDIL is starting up."; break;
- default: s = (theState < 50) ? "Unknown CDIL state." : "(User-defined CDIL state)";
- };
-
- strcpy((char*) theString, s);
- strcat((char*) theString, ": State #");
- NumToString(theState, (unsigned char*) theNum);
- strcat((char*) theString, (char*) p2cstr((unsigned char*)theNum));
-
- return (( char*) theString);
- }
-
-
- /*
- * Main
- *
- * This is the entry point for this application.
- */
- void main(void)
- {
- CommErr fErr;
- CursHandle W; /* Cursor handle to get cursors */
- DialogPtr splash; /* For use in splash screen */
- Handle MyMenu; /* my menu bar handle */
- Cursor myWatchCursor ; /* The watch "busy" cursor */
-
- #ifdef DEFINE_QD
- // This is needed for some compilers...
- QDGlobals qd;
- #endif
-
- /* Start out with the standard Macintosh initializations */
- MaxApplZone();
- InitGraf((Ptr)&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
- MoreMasters();
- MoreMasters();
- MoreMasters();
-
- fErr = CDInitCDIL() ;
- if (fErr) {
- PostAlertMessage("Error initializing CDIL", ErrorStrings((int) fErr, gTempBuffer), "", "");
- return;
- }
-
- // Initialize the libraries themselves (does not make a connection)
- fErr = FDInitFDIL();
- if (fErr) {
- PostAlertMessage("Error initializing FDIL", ErrorStrings((int) fErr, gTempBuffer), "", "");
- return;
- }
-
- // Set up the menus
- MyMenu = GetNewMBar(kMBarID);
- SetMenuBar(MyMenu);
-
- gAppleMenuHandle = GetMenuHandle(kAppleMenu);
- gFileMenuHandle = GetMenuHandle(kFileMenu);
- gEditMenuHandle = GetMenuHandle(kEditMenu);
- gTestHandle = GetMenuHandle(kTestMenu);
- gPortHandle = GetMenuHandle(kPortMenu);
- gFuncMenuHandle = GetMenuHandle(kFnMenu);
-
- // add desk accessories to the apple menu
- AppendResMenu(gAppleMenuHandle, 'DRVR');
-
- SetupPortMenu();
- if (gNumPorts==0){
- PostAlertMessage("Error getting serial port names", "", "", "");
- return;
- }
-
- CheckItem(gPortHandle, kSerialTool, false);
- CheckItem(gPortHandle, kModemTool, true); // default to the modem tool
- CheckItem(gPortHandle, kADSPTool, false);
- CheckItem(gPortHandle, kIRTool, false);
- gWhichTool = kModemTool;
-
- DisableExpertFuncs();
-
- DrawMenuBar();
-
- // Turn on the watch cursor while the splash screen is showing
- W = GetCursor (watchCursor);
- if (W)
- myWatchCursor = **W;
-
- SetCursor((CursPtr)&myWatchCursor);
- ShowCursor();
-
- ShowSplash(&splash);
-
- ourPipe = CDCreateCDILObject();
- if (!ourPipe) {
- PostAlertMessage("Error instantiating CDIL", "", "", "");
- return;
- }
-
- HideSplash(splash);
- HideCursor();
- SetCursor((const Cursor *)&qd.arrow);
- ShowCursor();
-
- EventLoop ();
-
- fErr = CDPipeDisconnect (ourPipe);
-
- CDDisposeCDILObject( ourPipe ) ;
- CDDisposeCDIL() ;
- #ifdef useASLM
- CleanupLibraryManager();
- #endif
- }
-
- /*
- * EventLoop
- *
- * Purpose: This is the main Macintosh event loop processor.
- * This function must handle any type of Macintosh event
- * like mouse clicks and keyboard events.
- */
- void EventLoop ( void )
- {
- EventRecord gERecord; /* Current Macintosh Toolbox event record */
- WindowPtr twindow;
- short part;
-
- do {
- CDIdle(ourPipe);
- WaitNextEvent(everyEvent, &gERecord, 30, nil);
-
- switch (gERecord.what) {
- case mouseDown:
- /* first see where the hit was */
- part = FindWindow(gERecord.where, &twindow);
- switch (part) {
-
- case inDesk: /* if they hit in desk, then the process manager */
- break; /* will switch us out, we don't need to do anything */
-
- case inMenuBar:
- DoMenuItem(MenuSelect(gERecord.where));
- break;
-
- case inSysWindow: /* pass to the system */
- SystemClick(&gERecord, twindow);
- break;
-
- case inContent: /* This app doesn't do windows */
- case inDrag:
- case inGrow:
- case inGoAway:
- case inZoomIn:
- case inZoomOut:
- break;
-
- }
- break;
-
- case keyUp: /* don't care */
- case mouseUp: /* don't care */
- case networkEvt: /* don't care */
- case driverEvt: /* don't care */
- case kHighLevelEvent: /* AppleEvents */
- break;
-
- case keyDown:
- case autoKey:
- if (gERecord.modifiers & cmdKey)
- DoMenuItem(MenuKey((short)gERecord.message & charCodeMask));
- else
- SysBeep(2);
- break;
-
- case diskEvt:
- /* We don't do anything special for disk events, this just passes them
- * to a function that checks for an error on the mount
- */
- DoDiskEvents((long)gERecord.message);
- break;
-
- default:
- break;
-
- }
- } while (gQuit != true);
- }
-
- /*
- * DoDeskAccCall
- *
- * DoDeskAccCall opens the requested DA
- */
-
- void DoDeskAccCall(MenuHandle themenu, long theit)
- {
- Str255 DAname;
-
- GetMenuItemText(themenu, (short)theit, DAname);
- OpenDeskAcc(DAname);
- } /* end DoDeskAccCall */
-
- /*
- * DoDiskEvents
- *
- * DoDiskEvents performs disk mount operations
- */
- void DoDiskEvents(long dinfo) /* hi word is error code, lo word is drive number */
- {
- short theHighWord, theLowWord, hdl;
- Point mountpoint = {
- 40, 40
- };
-
- theHighWord = HiWord(dinfo);
- theLowWord = LoWord(dinfo);
- if (theHighWord != noErr)/* something happened */ {
- hdl = DIBadMount(mountpoint, dinfo);
- }
- }
-
- /*
- * DoMenuItem
- *
- * DoMenuItem processes a menu event
- */
-
- Boolean DoMenuItem(long val)
- {
- short theLowWord, theHighWord;
- CommErr fErr = 0;
- Str255 stateString;
- CDIL_State state;
-
- theLowWord = LoWord(val);
- theHighWord = HiWord(val);
-
- switch (theHighWord) { /* switch off the menu number selected */
- case kAppleMenu: /* Apple menu */
- if (theLowWord != 1) /* if this was not About, it's a DA */
- DoDeskAccCall(gAppleMenuHandle, theLowWord);
- else
- Alert(kAboutDialog, nil); /* do about box */
- break;
-
- case kFileMenu: /* File menu */
- gQuit = true; /* only edit item */
- break;
-
- case kEditMenu: /* don't care */
- SysBeep(1);
- break;
-
- case kTestMenu: /* Test suites */
- switch(theLowWord) {
- case kSoupDrinkItem:
- fErr = SoupDrink();
- if (fErr)
- PostAlertMessage("Error from Soup Drink", ErrorStrings((int) fErr, gTempBuffer), "", "");
- break;
-
- case kNewNameItem: /* Create a new Names Soup entry on the Newton */
- fErr = UploadNewName();
- if (fErr)
- PostAlertMessage("Error from UploadNewName", ErrorStrings((int) fErr, gTempBuffer), "", "");
- break;
-
- default: /* Sanity check. Shouldn't get here */
- SysBeep(1);
- break;
- }
- break;
-
- case kPortMenu: // Choose a port…
- switch(theLowWord) {
- case kSerialTool:
- case kModemTool:
- case kADSPTool:
- case kIRTool:
- CheckItem(gPortHandle, kSerialTool, (theLowWord==kSerialTool));
- CheckItem(gPortHandle, kModemTool, (theLowWord==kModemTool));
- CheckItem(gPortHandle, kADSPTool, (theLowWord==kADSPTool));
- CheckItem(gPortHandle, kIRTool, (theLowWord==kIRTool));
- gWhichTool = theLowWord;
- break;
-
- default: {
- int i;
-
- for (i=0; i<gNumPorts; i++)
- CheckItem(gPortHandle, kFirstPortItem + i, (theLowWord== kFirstPortItem + i));
- gWhichPort = theLowWord;
- break;
- }
- }
- break;
-
- case kFnMenu: // Choose a function …
- switch(theLowWord) {
- case kFInitItem:
- fErr = InitializePipe();
- if (fErr)
- PostAlertMessage("InitializePipe returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
- break;
-
- case kFListenItem:
- fErr = CDPipeListen(ourPipe, kDefaultTimeout, (CDILCompletionProcPtr)ListenCallback, 0) ;
- if (fErr)
- PostAlertMessage("CDPipeListen returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
- break;
-
- case kFAcceptItem:
- fErr = CDPipeAccept(ourPipe) ;
- if (fErr)
- PostAlertMessage("CDPipeAccept returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
- break;
-
- case kFAbortItem:
- fErr = CDPipeAbort(ourPipe, kAllPipes) ;
- if (fErr)
- PostAlertMessage("CDPipeAbort returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
- break;
-
- case kFDiscItem:
- fErr = CDPipeDisconnect(ourPipe) ;
- if (fErr)
- PostAlertMessage("CDPipeDisconnect returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
- break;
-
- case kFReadItem:
- SysBeep(1);
- break;
-
- case kFCountItem:
- SysBeep(1);
- break;
-
- case kFWriteItem:
- SysBeep(1);
- break;
-
- case kFGetStateItem:
- state = CDGetPipeState(ourPipe);
-
- PostAlertMessage("Current state:", StateStrings(state, stateString), "", "");
- break;
-
- case kFSetStateItem: /* Set State number (e.g. kCDIL_Busy) */
- SysBeep(1);
- break;
-
- case kToggleEncryption:
- if (gEncrypt) {
- CDEncryptFunction(ourPipe, (CDILEncryptionProcPtr) nil, 0 ) ;
- CDDecryptFunction(ourPipe, (CDILDecryptionProcPtr) nil, 0 ) ;
- gEncrypt = false ;
- }
- else {
- CDEncryptFunction(ourPipe, (CDILEncryptionProcPtr) encryptProc, 100 ) ;
- CDDecryptFunction(ourPipe, (CDILDecryptionProcPtr) decryptProc, 100 ) ;
- gEncrypt = true ;
- }
- CheckItem(gFuncMenuHandle, kToggleEncryption, gEncrypt);
-
- break;
-
- case kToggleByteSwap:
- if (gByteSwap)
- gByteSwap = false ;
- else
- gByteSwap = true ;
-
- CheckItem(gFuncMenuHandle, kToggleByteSwap, gByteSwap);
- break;
-
- case kToggleUnicode:
- if (gUseUnicode)
- gUseUnicode = false ;
- else
- gUseUnicode = true ;
-
- CheckItem(gFuncMenuHandle, kToggleUnicode, gUseUnicode);
- break;
- case kExpertModeToggle:
- if (gExpertMode) {
- gExpertMode = false ;
- DisableExpertFuncs();
- }
- else {
- gExpertMode = true ;
- EnableExpertFuncs();
- }
-
- CheckItem(gFuncMenuHandle, kExpertModeToggle, gExpertMode);
- break;
-
- default:
- SysBeep(1); // Sanity check; shouldn't get here
- break;
- }
-
- }
- HiliteMenu(0); // Unhilite the menu label itself
- return noErr;
- } /* end DoMenuItem */
-
-
- void EnableExpertFuncs(void) {
- EnableItem(gFuncMenuHandle,kFInitItem);
- EnableItem(gFuncMenuHandle,kFListenItem);
- EnableItem(gFuncMenuHandle,kFAcceptItem);
- EnableItem(gFuncMenuHandle,kFAbortItem);
- EnableItem(gFuncMenuHandle,kFDiscItem);
- //EnableItem(gFuncMenuHandle,kFReadItem);
- //EnableItem(gFuncMenuHandle,kFCountItem);
- //EnableItem(gFuncMenuHandle,kFWriteItem);
- //EnableItem(gFuncMenuHandle,kFSetStateItem);
- EnableItem(gFuncMenuHandle,kToggleEncryption);
- EnableItem(gFuncMenuHandle,kToggleByteSwap);
- EnableItem(gFuncMenuHandle,kToggleUnicode);
- }
-
- void DisableExpertFuncs(void) {
- DisableItem(gFuncMenuHandle,kFInitItem);
- DisableItem(gFuncMenuHandle,kFListenItem);
- DisableItem(gFuncMenuHandle,kFAcceptItem);
- DisableItem(gFuncMenuHandle,kFAbortItem);
- DisableItem(gFuncMenuHandle,kFDiscItem);
- DisableItem(gFuncMenuHandle,kFReadItem);
- DisableItem(gFuncMenuHandle,kFCountItem);
- DisableItem(gFuncMenuHandle,kFWriteItem);
- DisableItem(gFuncMenuHandle,kFSetStateItem);
- DisableItem(gFuncMenuHandle,kToggleEncryption);
- DisableItem(gFuncMenuHandle,kToggleByteSwap);
- DisableItem(gFuncMenuHandle,kToggleUnicode);
- }
-
-
- long CurrentTimeInSeconds()
- // return something indicating what time it is, in seconds units
- // This is only used to compare one time against another; it does
- // not need to have any relationship to the time of day.
- {
- return (TickCount() / 60);
- }
-